Skip to content

feat(runtime-interface-client): Add Lambda-Runtime-Invocation-Id support for cross-wiring protection#624

Open
vip-amzn wants to merge 1 commit into
mainfrom
feat/invocation-id-cross-wiring
Open

feat(runtime-interface-client): Add Lambda-Runtime-Invocation-Id support for cross-wiring protection#624
vip-amzn wants to merge 1 commit into
mainfrom
feat/invocation-id-cross-wiring

Conversation

@vip-amzn

Copy link
Copy Markdown

Summary

Add Lambda-Runtime-Invocation-Id header support for cross-wiring protection.

The RIC now echoes the invocation ID received from RAPID on /next back on /response and /error, enabling RAPID to detect and reject stale responses from timed-out invocations.

Problem

On Lambda Managed Instances (LMI) and On-Demand (OD), when an invoke times out, the runtime process continues running in the background. If a new invoke arrives with the same requestId, RAPID accepts it. The still-running old invocation eventually posts its response, and RAPID matches it to the new invoke — delivering the wrong response (cross-wiring).

Solution

RAPID sends a unique per-invoke identifier via Lambda-Runtime-Invocation-Id header on /next. The runtime echoes it back on /response and /error. RAPID validates the match before accepting the response.

Changes

  • aws-lambda-cpp-0.2.7/runtime.h: Added invocation_id field to invocation_request, added param to post_success/post_failure/do_post
  • aws-lambda-cpp-0.2.7/runtime.cpp: Parse header in get_next(), add to curl request in do_post() when non-empty
  • NativeClient.cpp/.h: JNI reads invocation_id from C++ response, passes to Java; postInvocationResponse accepts nullable invocationId
  • InvocationRequest.java: New invocationId field
  • NativeClient.java: Updated native method signature
  • LambdaRuntimeApiClient.java/Impl: reportInvocationSuccess/reportInvocationError accept invocationId
  • AWSLambda.java: Thread invocationId through runtime loop
  • Unit tests: Updated assertions for new parameter
  • Version bump: 2.11.0 → 2.12.0

Backward Compatibility

Fully backward compatible in both directions:

  • If RAPID doesn't send the header → RIC doesn't see it → doesn't echo → no behavior change
  • If RIC doesn't echo it (old version) → RAPID skips validation → no behavior change

…ort for cross-wiring protection

Echo the invocation ID received from RAPID on /next back on /response
and /error, enabling RAPID to detect and reject stale responses from
timed-out invocations. Fully backward compatible.

@rudraroop rudraroop left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good overall - my major point of feedback would be adding a test for the positive path where invocation IDs are non-null

Have added some casing/hardcoding related comments - whatever I could see

headers.put(ERROR_TYPE_HEADER, error.errorType.getRapidError());

if (invocationId != null) {
headers.put("Lambda-Runtime-Invocation-Id", invocationId);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the other headers in this file are declared as constants at the start of the file. I would suggest keeping that uniform and making a constant above for this one as well

static constexpr auto DEADLINE_MS_HEADER = "lambda-runtime-deadline-ms";
static constexpr auto FUNCTION_ARN_HEADER = "lambda-runtime-invoked-function-arn";
static constexpr auto TENANT_ID_HEADER = "lambda-runtime-aws-tenant-id";
static constexpr auto INVOCATION_ID_HEADER = "lambda-runtime-invocation-id";

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The "L" is capitalised in the java file but lowercase here


LambdaError lambdaError = new LambdaError(errorRequest, rapidErrorType);
lambdaRuntimeApiClientImpl.reportInvocationError(requestId, lambdaError);
lambdaRuntimeApiClientImpl.reportInvocationError(requestId, lambdaError, null);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should have one test for reportInvocationError which tests a positive path i.e. one where the Lambda-Runtime-Invocation-Id is actually getting passed instead of null

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same feedback for positive path test inclusion as in this file LambdaRuntimeApiClientImplTest.java‎

headers = curl_slist_append(headers, "transfer-encoding:");
headers = curl_slist_append(headers, m_user_agent_header.c_str());
if (!invocation_id.empty()) {
headers = curl_slist_append(headers, ("lambda-runtime-invocation-id: " + invocation_id).c_str());

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should use the header constant here instead of hardcoding again?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants